package com.zhufeng.gateway.db.route;

import com.alibaba.fastjson.JSONObject;
import com.zhufeng.user.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.handler.AsyncPredicate;
import org.springframework.cloud.gateway.handler.predicate.ReadBodyRoutePredicateFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.function.Predicate;

/**
 * @ClassName: CustomReadBodyRoutePredicateFactory
 * @Description TODO
 * @author 月夜烛峰
 * @date 2022/9/16 14:27
 */
@Slf4j
public class CustomReadBodyRoutePredicateFactory extends ReadBodyRoutePredicateFactory {

    private static final String TEST_ATTRIBUTE = "read_body_predicate_test_attribute";

    private static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";

    private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies
            .withDefaults().messageReaders();

    public CustomReadBodyRoutePredicateFactory() {
        super();
    }



    @Override
    public AsyncPredicate<ServerWebExchange> applyAsync(ReadBodyRoutePredicateFactory.Config config) {

        return exchange -> {
            Predicate<JSONObject> predicate = msgInfo -> {
                log.info("请求数据:" + msgInfo);

                return true;
            };

//            Predicate<UserInfo> prd = userInfo -> {
//                log.info("请求数据:" + userInfo.getUserName());
//                return true;
//            };

            config.setPredicate(predicate);

            log.info("打印属性ContentType:{}",exchange.getRequest().getHeaders().getContentType());
            log.info("打印属性attributes:{}",exchange.getAttributes().toString());
            log.info("打印属性formdata:{}",exchange.getFormData().toString());
            log.info("打印属性queryparam:{}",exchange.getRequest().getQueryParams());


            Class<JSONObject> inClass = config.getInClass();

            //Class<UserInfo> inClass = UserInfo.class;
            log.info("打印inClass:{}",inClass);



            Object cachedBody = exchange.getAttribute(CACHE_REQUEST_BODY_OBJECT_KEY);
            log.info("cachedBody:{}",cachedBody);

            // 获取 MediaType
            MediaType mediaType = exchange.getRequest().getHeaders().getContentType();

            if("com.zhufeng.user.UserInfo".equals(inClass.getName())){


                log.info("类型:{}",mediaType.getType());
                //String userStr = String.class.cast(inClass);
                //JSONObject.toJSON(inClass);
                log.info("userStr:{}",JSONObject.toJSON(inClass));
                String userStr = JSONObject.toJSONString(inClass);
                UserInfo user = JSONObject.parseObject(userStr,UserInfo.class);
                log.info(user.getUserId()+":"+user.getUserName());
            }


            if (cachedBody != null) {
                try {
                    boolean test = config.getPredicate().test(cachedBody);
                    exchange.getAttributes().put(TEST_ATTRIBUTE, test);
                    return Mono.just(test);
                } catch (ClassCastException e) {
                    if (log.isDebugEnabled()) {
                        log.debug("Predicate test failed because class in predicate "
                                + "does not match the cached body object", e);
                    }
                }
                return Mono.just(false);
                /**
            } else {
                return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange,
                        (serverHttpRequest) -> ServerRequest
                                .create(exchange.mutate().request(serverHttpRequest)
                                        .build(), messageReaders)
                                .bodyToMono(inClass)
                                .doOnNext(objectValue -> exchange.getAttributes()
                                        .put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue))
                                .map(objectValue -> config.getPredicate()
                                        .test(objectValue)));
                 */
            } else {
                return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> ServerRequest.create(exchange.mutate().request(serverHttpRequest).build(), messageReaders).bodyToMono(inClass).doOnNext((objectValue) -> {
                    exchange.getAttributes().put(CACHE_REQUEST_BODY_OBJECT_KEY, objectValue);
                }).map((objectValue) -> {
                    log.info("objectValue:{}",JSONObject.toJSONString(objectValue));
                    //UserInfo userInfo = (UserInfo)objectValue;
                    //log.info(userInfo.getUserId()+":"+userInfo.getUserName());
                    return config.getPredicate().test(objectValue);
                }));
            }
        };
    }

}

